package com.btcode.web.safe.filter;

import com.btcode.exception.MsgException;
import com.btcode.web.core.respone.JsonRespone;
import com.btcode.web.core.respone.ResultFlag;
import com.btcode.web.core.unit.URLUtil;
import com.btcode.web.safe.service.IVerifyService;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletResponse;

/**
 * 请求认证filter，用于验证当前请求是否是合法用户 <br/> 如果认证不通过，则跳转到登陆页面
 *
 * @author gislin
 */
public class UserIdentityFilter implements Filter {

    private IVerifyService verifyService;

    /**
     * 当认证不通过的时候，是否跳转页面，否则通过json返回信息，默认为否
     */
    private boolean sendRedirectWhenError = false;

    /**
     * 入口和登录页面映射配置
     */
    private List<EntranceAndLogin> mulitEntrances = new ArrayList<>();

    /**
     * 项目名称
     */
    private String projectName;

    @Override
    public void destroy() {
        // TODO Auto-generated method stub
    }

    public UserIdentityFilter(String projectName){
        this.projectName = projectName;
    }

    public void setVerifyService(IVerifyService verifyService) {
        this.verifyService = verifyService;
    }

    /**
     * 增加入口
     * @param entrance 入口信息
     */
    public void addEntrance(EntranceAndLogin entrance){
        mulitEntrances.add(entrance);
    }

    /**
     * 增加入口
     * @param entrances 入口信息
     */
    public void addEntrances(List<EntranceAndLogin> entrances){
        mulitEntrances.addAll(entrances);
    }

    @Override
    public void doFilter(ServletRequest arg0, ServletResponse arg1, FilterChain arg2)
        throws IOException, ServletException {

        String uri = URLUtil.getURLWithoutProjectName(arg0);

        /**
         * 如果是登录的地址，直接放过
         */
        if (isLoginUrl(uri)) {
            arg2.doFilter(arg0, arg1);
            return;
        }

        /**
         * 用于处理由UrlMappingServlet映射的地址
         */
        Object noeCheck = arg0.getAttribute("noeCheck");

        if (noeCheck != null) {
            arg2.doFilter(arg0, arg1);
            return;
        }

        /**
         * 如果是免验证地址，直接放过
         */
        if (verifyService.canAccessWithoutAuthentication(arg0)) {
            arg2.doFilter(arg0, arg1);
            return;
        }

        if (!verifyService.canAccess(arg0)) {
            HttpServletResponse respone = (HttpServletResponse) arg1;
            if(sendRedirectWhenError){
                String loginUrl = getLoginUrl(uri);
                respone.sendRedirect("/"+projectName+loginUrl+"?url="+uri);
            }
            else {
                respone.setStatus(403);
                JsonRespone.getInstance(JsonRespone.class).outputObj("无访问权限", ResultFlag.ERROR,
                                                                     "无访问权限");
            }
            return;
        }

        arg2.doFilter(arg0, arg1);
    }

    /**
     * 根据请求的地址获取登录地址
     * @param requestUrl 前端锁请求的地址
     * @return 对应的登录地址，如果没有匹配的，则返回第一个入口信息的登录地址
     */
    private String getLoginUrl(String requestUrl){

        for(EntranceAndLogin entrance : mulitEntrances){
            if(requestUrl.startsWith(entrance.getEntrancePrefix())){
                return entrance.getLoginUrl();
            }
        }
        return mulitEntrances.get(0).getLoginUrl();
    }

    /**
     * 判断所请求的地址是否是登录地址
     * @param requestUrl 前端锁请求的地址
     * @return 如果该请求地址和入口信息中的登录日志想匹配，则返回true，否则则返回false
     */
    private boolean isLoginUrl(String requestUrl){
        for(EntranceAndLogin entrance : mulitEntrances){
            if(requestUrl.equals(entrance.getLoginUrl())){
                return true;
            }
        }
        return false;
    }

    @Override
    public void init(FilterConfig arg0) {

        if(mulitEntrances.size()==0){
            throw  new MsgException("入口信息不能为空");
        }

    }
}
